package com.hyt.it.ogt.pj.service.impl;

import java.math.BigDecimal;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.RemoteUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.data.Constants;
import com.hyt.it.ogt.pj.common.MarkException;
import com.hyt.it.ogt.pj.common.ResponseCode;
import com.hyt.it.ogt.pj.feign.KwClient;
import com.hyt.it.ogt.pj.mapper.PaperMapper;
import com.hyt.it.ogt.pj.model.entity.Paper;
import com.hyt.it.ogt.pj.model.entity.PaperItem;
import com.hyt.it.ogt.pj.model.entity.PaperItemFile;
import com.hyt.it.ogt.pj.model.entity.PieceScore;
import com.hyt.it.ogt.pj.model.entity.Subject;
import com.hyt.it.ogt.pj.model.vo.ItemDataVO;
import com.hyt.it.ogt.pj.model.vo.ItemType;
import com.hyt.it.ogt.pj.model.vo.OptionsDataVO;
import com.hyt.it.ogt.pj.model.vo.PackageDataVO;
import com.hyt.it.ogt.pj.model.vo.PaperDataVO;
import com.hyt.it.ogt.pj.model.vo.ResourceAttr;
import com.hyt.it.ogt.pj.model.vo.TopicDataVO;
import com.hyt.it.ogt.pj.service.IPaperItemFileService;
import com.hyt.it.ogt.pj.service.IPaperItemService;
import com.hyt.it.ogt.pj.service.IPaperService;
import com.hyt.it.ogt.pj.service.IPieceScoreService;
import com.hyt.it.ogt.pj.service.ISubjectService;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 试卷表 服务实现类
 * </p>
 *
 * @author qiaozj
 * @since 2020-07-09
 */
@Service
@Slf4j
public class PaperServiceImpl extends BaseServiceImpl<PaperMapper, Paper> implements IPaperService {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private KwClient kwClient;

    @Autowired
    private ISubjectService subjectService;

    @Autowired
    private IPaperItemService paperItemService;

    @Autowired
    private IPaperService paperService;

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private IPieceScoreService pieceScoreService;

    @Autowired
    private IPaperItemFileService paperItemFileService;

    /**
     * 初始化试卷试题
     *
     * @param projectId 评卷项目id
     * @throws Exception 异常
     */
    @Override
    public void initPaper(String projectId, String admissionNum) {
        // 如果admissionNum不为空则为增量数据
        ApiResponse<List<PackageDataVO>> res = kwClient.getPapers(projectId, projectId, admissionNum);
        log.info(">>>拉取到的评卷试卷数据:{}", JSONObject.toJSONString(res));
        List<PackageDataVO> packages = res.getData();
        List<PaperDataVO> papers = packageToPaper(packages);
        if (CollectionUtils.isEmpty(papers)) {
            throw new MarkException(ResponseCode.INIT_PROJECT_NO_PAPER.toString());
        }
        // 保存试卷信息
        for (PaperDataVO paperVo : papers) {
            String paperId = paperVo.getPaperId();
            Integer paperVersion = paperVo.getPaperVersion();
            Integer packageVersion = paperVo.getPackageVersion();
            Paper existPaper = existPaper(projectId, paperVo.getSubjectId(), paperId, paperVersion, packageVersion);
            // 若库中存在该试卷信息，说明该试卷已经初始化过了，跳过该试卷
            if (existPaper != null) {
                continue;
            }
            Paper paper = new Paper();
            paper.setPaperId(paperId);
            paper.setPaperVersion(paperVo.getPaperVersion());
            paper.setPaperName(paperVo.getPaperName());
            paper.setProjectId(projectId);
            paper.setSubjectId(paperVo.getSubjectId());
            paper.setPaperScore(paperVo.getPaperScore());
            paper.setObjectiveScore(paperVo.getObjectiveItemScore());
            paper.setSubjectiveScore(paperVo.getSubjectiveItemScore());
            paper.setPackageId(paperVo.getPackageId());
            paper.setPackageVersion(paperVo.getPackageVersion());
            paper.setSort(paperVo.getSort());
            this.save(paper);
            // 初始化试题
            initPaperItem(paperVo, paper);
        }
    }

    /**
     * 初始化试卷试题
     *
     * @param projectId 评卷项目id
     * @throws Exception 异常
     */
    @Override
    public Integer initPaperBySubjets(String projectId, String admissionNum, List<Subject> subjects) throws Exception {
        if (CollectionUtils.isNotEmpty(subjects)) {
            for (Subject subject : subjects) {
                String subjectId = subject.getId();
                // 用是否传准考证号来区分是否为增量初始化试卷试题
                ApiResponse<List<PackageDataVO>> res = null;
                if (StringUtils.isEmpty(admissionNum)) {
                    res = kwClient.getPapers(projectId, subjectId, null);
                } else {
                    res = kwClient.getPapers(projectId, subjectId, admissionNum);
                }
                if (null == res || CollectionUtils.isEmpty(res.getData())) {
                    log.error("## 获取的初始化试卷试题：project:{},获取不到试卷信息, res:{}", projectId, JSON.toJSON(res));
                    return ResponseCode.INIT_PROJECT_NO_PAPER;
                }
                List<PackageDataVO> packages = res.getData();
                List<PaperDataVO> papers = packageToPaper(packages);
                if (CollectionUtils.isNotEmpty(papers)) {
                    for (PaperDataVO paperVo : papers) {
                        String paperId = paperVo.getPaperId();
                        Integer paperVersion = paperVo.getPaperVersion();
                        String packageId = paperVo.getPackageId();
                        Integer packageVersion = paperVo.getPackageVersion();
                        log.info("## existPaper：{},{},{},{},{},{}", projectId, subjectId, paperId, paperVersion, packageId, packageVersion);
                        Paper existPaper = existPaper(projectId, subjectId, paperId, paperVersion, packageId, packageVersion);
                        log.info("## existPaper：{}", null != existPaper);
                        // 若库中存在该试卷信息，说明该试卷已经初始化过了，单试卷还是null, 试卷包更新成最新的试卷包版本
                        if (existPaper != null) {
                            continue;
                        } else {
                            // 如果存在更新试卷包版本
                            if (!StringUtils.isEmpty(packageId)) {
                                Paper existPaperInPackage = existPaper(projectId, subjectId, paperId, paperVersion, null, null);
                                if (null != existPaperInPackage) {
                                    existPaperInPackage.setPackageVersion(packageVersion);
                                    paperService.getBaseMapper().updateById(existPaperInPackage);
                                }
                            }
                        }
                        Paper paper = new Paper();
                        paper.setPaperId(paperId);
                        paper.setPaperVersion(paperVo.getPaperVersion());
                        paper.setPaperName(paperVo.getPaperName());
                        paper.setProjectId(subject.getProjectId());
                        paper.setSubjectId(subjectId);
                        paper.setPaperScore(paperVo.getPaperScore());
                        paper.setObjectiveScore(paperVo.getObjectiveItemScore());
                        paper.setSubjectiveScore(paperVo.getSubjectiveItemScore());
                        paper.setPackageId(paperVo.getPackageId());
                        paper.setPackageVersion(paperVo.getPackageVersion());
                        paper.setSort(paperVo.getSort());
                        log.error("# b保存的内容是:{}", JSON.toJSON(paperVo));
                        this.save(paper);
                        // 初始化试题
                        initPaperItem(paperVo, paper);
                    }
                } else {
                    return ResponseCode.INIT_PROJECT_NO_PAPER;
                }
            }
        }
        return ResponseCode.SUCCESS;
    }

    @Override
    public List<Paper> selectByProject(String projectId) {
        return null;
    }

    @Override
    public Paper existPaper(String projectId, String subjectId, String paperId, Integer paperVersion, Integer packageVersion) {
        return paperMapper.existPaper(projectId, subjectId, paperId, paperVersion, packageVersion);
    }

    @Override
    public Paper existPaper(String projectId, String subjectId, String paperId, Integer paperVersion, String packageId, Integer packageVersion) {
        return null;
    }

    /**
     * 试卷包list转成试卷list
     *
     * @param packages
     * @return
     */
    private List<PaperDataVO> packageToPaper(List<PackageDataVO> packages) {
        List<PaperDataVO> allPapers = new ArrayList<>();
        List<PaperDataVO> paperVOs = null;
        for (PackageDataVO packageVO : packages) {
            paperVOs = packageVO.getPaperDataVOList();
            if (packageVO.getId() == null) {
                // 单体试卷
                if (paperVOs.size() > 0) {
                    PaperDataVO paperVO = paperVOs.get(0);
                    paperVO.setSort(1);
                    allPapers.add(paperVO);
                }
            } else {
                int i = 0;
                for (PaperDataVO paperVO : paperVOs) {
                    paperVO.setPackageId(packageVO.getId());
                    paperVO.setPackageVersion(packageVO.getVersion());
                    paperVO.setSort(i += 1);
                    allPapers.add(paperVO);
                }
            }
        }
        return allPapers;
    }


    /**
     * 初始化试题
     *
     * @param paperVo 试卷
     */
    private void initPaperItem(PaperDataVO paperVo, Paper paper) {
        String paperId = paper.getId();
        List<TopicDataVO> topicDataList = paperVo.getTopicDataList();
        List<PaperItem> paperItems = new ArrayList<>();
        for (TopicDataVO topicDataVo : topicDataList) {
            PaperItem paperItem = new PaperItem();
            paperItem.setId(UUIDUtils.newSortUUID());
            paperItem.setTopicId(topicDataVo.getTopicId());
            paperItem.setPaperId(paperId);
            paperItem.setParentId("0");
            paperItem.setItemName(topicDataVo.getTopicName());
            paperItem.setItemCode(topicDataVo.getTopicSort().toString());
            paperItem.setIsComposite(true);
            paperItem.setItemType("topic");
            paperItem.setItemLevel(0);
            // 设置题干
            paperItem.setItemStem(topicDataVo.getTopicDescription());
            // 设置试题分数
            paperItem.setScore(topicDataVo.getTopicScore());
            // 设置排序
            paperItem.setOrderNum(topicDataVo.getTopicSort());
            paperItems.add(paperItem);
            // 初始化大题下面的小题
            initBigItem(paperItem.getId(), topicDataVo, paperItems, paper);
            // 保存题目附件信息
            savePaperItemFile(topicDataVo.getItemDataList(), paper);
        }
        paperItemService.saveBatch(paperItems);
    }

    /**
     * 保存题目信息
     *
     * @param itemDataVOS
     * @param paper
     */
    private void savePaperItemFile(List<ItemDataVO> itemDataVOS, Paper paper) {
        for (ItemDataVO itemDataVO : itemDataVOS) {
            List<ResourceAttr> stemAttrs = itemDataVO.getStemAttrs();
            List<ResourceAttr> answerAttrs = itemDataVO.getAnswerAttrs();
            List<ResourceAttr> descriptionAttrs = itemDataVO.getDescriptionAttrs();
            // 合并集合
            List<ResourceAttr> resourceAttrList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(stemAttrs)) {
                resourceAttrList = CollectionUtil.unionAll(resourceAttrList, stemAttrs);
            }
            if (CollectionUtils.isNotEmpty(answerAttrs)) {
                resourceAttrList = CollectionUtil.unionAll(resourceAttrList, answerAttrs);
            }
            if (CollectionUtils.isNotEmpty(descriptionAttrs)) {
                resourceAttrList = CollectionUtil.unionAll(resourceAttrList, descriptionAttrs);
            }

            List<PaperItemFile> paperItemFiles = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(resourceAttrList)) {
                for (ResourceAttr item : resourceAttrList) {
                    PaperItemFile paperItemFile = new PaperItemFile();
                    paperItemFile.setFileLocation(item.getType());
                    paperItemFile.setFileType(item.getFileType());
                    paperItemFile.setItemId(itemDataVO.getItemId());
                    paperItemFile.setPaperId(paper.getPaperId());
                    paperItemFile.setPaperVersion(paper.getPaperVersion());
                    paperItemFile.setSort(item.getOptionSort());
                    paperItemFile.setUrl(item.getUrl());
                    paperItemFile.setProjectId(paper.getProjectId());
                    paperItemFiles.add(paperItemFile);
                }
                paperItemFileService.saveBatch(paperItemFiles);
            }
        }
    }


    /**
     * 初始化试题
     *
     * @param topicDataVo 大题
     * @param paperItems  试题列表
     * @param paper       试卷
     */
    private void initBigItem(String paperItemId, TopicDataVO topicDataVo, List<PaperItem> paperItems, Paper paper) {
        String paperId = paper.getId();
        List<ItemDataVO> itemDataVOS = topicDataVo.getItemDataList();
        for (ItemDataVO itemDataVO : itemDataVOS) {
            PaperItem bigItem = new PaperItem();
            bigItem.setId(UUIDUtils.newSortUUID());
            bigItem.setTopicId(itemDataVO.getItemId());
            bigItem.setPaperId(paperId);
            bigItem.setParentId(paperItemId);
            // 大题没有名称
            // itemCode
            bigItem.setItemCode(itemDataVO.getItemSort().toString());
            bigItem.setIsComposite(itemDataVO.getComposite());
            String itemType = itemDataVO.getItemType();
            bigItem.setItemType(itemType);
            bigItem.setItemLevel(1);
            // TODO 大题是否需要标明主客观
            bigItem.setItemViewPoint(itemDataVO.getObjective());
            bigItem.setItemStem(itemDataVO.getItemContent());
            bigItem.setAnswer(itemDataVO.getAnswer());
            bigItem.setAnalysis(itemDataVO.getDescription());
            bigItem.setOrderNum(itemDataVO.getItemSort());
            if (itemDataVO.getScore() != null) {
                bigItem.setScore(new BigDecimal(itemDataVO.getScore()));
            }
            paperItems.add(bigItem);

            if ("fill_in_blanks".equalsIgnoreCase(itemType)) {
                List<OptionsDataVO> optionsDataVOS = itemDataVO.getOptionsDataList();
                for (OptionsDataVO optionsDataVO : optionsDataVOS) {
                    PaperItem optionItem = new PaperItem();
                    optionItem.setId(UUIDUtils.newSortUUID());
                    optionItem.setTopicId(optionsDataVO.getOptionId());
                    optionItem.setPaperId(paperId);
                    optionItem.setParentId(bigItem.getId());
                    // 填空题选项没有题干
                    // optionItem.setItemName(optionsDataVO.getOptionName());
                    optionItem.setIsComposite(optionsDataVO.getComposite());
                    optionItem.setItemType("option");
                    optionItem.setItemLevel(2);
                    optionItem.setItemViewPoint(false);
                    // 填空题选项答案
                    optionItem.setAnswer(optionsDataVO.getOptionContent());
                    String optionScore = optionsDataVO.getScore();
                    optionItem.setOrderNum(optionsDataVO.getOptionSort());
                    if (optionScore != null) {
                        optionItem.setScore(new BigDecimal(optionScore));
                    }
                    optionItem.setItemCode(String.valueOf(optionsDataVO.getOptionSort()));
                    paperItems.add(optionItem);
                }
            } else {
                // 如果不是填空题
                List<ItemDataVO> childItemList = itemDataVO.getChildItemList();
                // 复合题是不是主观题的标志，默认不是，如果有小题是主观题则为是
                boolean flag = false;
                // 保存复合题里面的音视频
                savePaperItemFile(childItemList, paper);
                for (ItemDataVO childItem : childItemList) {
                    //复合题有一道主观题，这道符合题就算主观题
                    if (!childItem.getObjective()) {
                        flag = true;
                    }
                    PaperItem subItem = new PaperItem();
                    subItem.setId(UUIDUtils.newSortUUID());
                    subItem.setTopicId(childItem.getItemId());
                    subItem.setPaperId(paperId);
                    subItem.setParentId(bigItem.getId());
                    // 大题没有名称
                    subItem.setItemCode(childItem.getItemSort().toString());
                    subItem.setIsComposite(childItem.getComposite());
                    String subItemType = childItem.getItemType();
                    subItem.setItemType(subItemType);
                    subItem.setItemLevel(2);
                    // TODO 大题是否需要标明主客观
                    subItem.setItemViewPoint(childItem.getObjective());
                    subItem.setItemStem(childItem.getItemContent());
                    subItem.setAnswer(childItem.getAnswer());
                    subItem.setAnalysis(childItem.getDescription());
                    subItem.setOrderNum(childItem.getItemSort());
                    if (childItem.getScore() != null) {
                        subItem.setScore(new BigDecimal(childItem.getScore()));
                    }
                    paperItems.add(subItem);

                    if ("fill_in_blanks".equalsIgnoreCase(subItemType)) {
                        List<OptionsDataVO> optionsDataVOS = itemDataVO.getOptionsDataList();
                        for (OptionsDataVO optionsDataVO : optionsDataVOS) {
                            PaperItem optionItem = new PaperItem();
                            optionItem.setId(UUIDUtils.newSortUUID());
                            optionItem.setTopicId(optionsDataVO.getOptionId());
                            optionItem.setPaperId(paperId);
                            optionItem.setParentId(optionsDataVO.getItemId());
                            // 大题没有名称
                            // optionItem.setItemName(optionsDataVO.getOptionName());
                            optionItem.setIsComposite(optionsDataVO.getComposite());
                            optionItem.setItemType("option");
                            optionItem.setItemLevel(2);
                            optionItem.setItemViewPoint(false);
                            optionItem.setAnswer(optionsDataVO.getOptionContent());
                            optionItem.setOrderNum(optionsDataVO.getOptionSort());
                            optionItem.setItemCode(String.valueOf(optionsDataVO.getOptionSort()));
                            if (optionsDataVO.getScore() != null) {
                                optionItem.setScore(new BigDecimal(optionsDataVO.getScore()));
                            }
                            paperItems.add(optionItem);
                        }
                    }
                }
            }
        }
    }

    /**
     * 根据科目id获取试卷
     *
     * @param subjectId
     * @return
     */
    @Override
    public List<Paper> selectBySubject(String projectId, String subjectId) {
        List<Paper> papers = paperMapper.selectBySubject(projectId, subjectId);
        return papers;
    }

    @Override
    public List<ItemType> selectItemTypes(String paperId, String subjectId, String pieceId, String encodeId) {
        List<ItemType> itemTypes = paperMapper.selectItemTypes(paperId);
        PieceScore pieceScore = pieceScoreService.selectPieceScore(subjectId, pieceId, encodeId);
        for (ItemType itemType : itemTypes) {
            itemType.setEncodeId(encodeId);
            itemType.setTotalScore(pieceScore.getScore());
            if (itemType.getItemViewPoint()) {
                itemType.setTypeName("客观题");
                itemType.setTypeScore(pieceScore.getObjectiveScore());
            } else {
                itemType.setTypeName("主观题");
                itemType.setTypeScore(pieceScore.getSubjectiveScore());
            }
        }
        //如果只有一条主观题，则拼凑一条客观题
        if (itemTypes.size() == 1 && null != itemTypes.get(0).getItemViewPoint()
                && itemTypes.get(0).getItemViewPoint() == false) {
            ItemType itemType = new ItemType();
            itemType.setEncodeId(encodeId);
            itemType.setTypeScore(pieceScore.getObjectiveScore());
            itemType.setItemNum(0);
            itemType.setTypeName("客观题");
            itemType.setItemViewPoint(true);
            itemTypes.add(itemType);
        }
        return itemTypes;
    }

    @Override
    public void savePaper(String projectId, List<PaperDataVO> papers) {
        for (PaperDataVO paperVo : papers) {
            String paperId = paperVo.getPaperId();
            Integer paperVersion = paperVo.getPaperVersion();
            Integer packageVersion = paperVo.getPackageVersion();
            Paper existPaper = existPaper(projectId, paperVo.getSubjectId(), paperId, paperVersion, packageVersion);
            // 若库中存在该试卷信息，说明该试卷已经初始化过了，跳过该试卷
            if (existPaper != null) {
                continue;
            }
            Paper paper = new Paper();
            paper.setPaperId(paperId);
            paper.setPaperVersion(paperVo.getPaperVersion());
            paper.setPaperName(paperVo.getPaperName());
            paper.setProjectId(projectId);
            paper.setSubjectId(paperVo.getSubjectId());
            paper.setPaperScore(paperVo.getPaperScore());
            paper.setObjectiveScore(paperVo.getObjectiveItemScore());
            paper.setSubjectiveScore(paperVo.getSubjectiveItemScore());
            paper.setPackageId(paperVo.getPackageId());
            paper.setPackageVersion(paperVo.getPackageVersion());
            paper.setSort(paperVo.getSort());
            savePaper(paper);
            // 初始化试题
            initPaperItem(paperVo, paper);

            // 查询属性文件并保存
            log.info("打印查询参数： paperId:{}, paperVersion:{}", paperId, paperVersion);
            List<PaperItemFile> paperItemFileData = this.getPaperItemFileData(projectId, paperId, String.valueOf(paperVersion));
            if (CollectionUtil.isNotEmpty(paperItemFileData)) {
                paperItemFileService.saveBatch(paperItemFileData);
            }
        }
    }

    /**
     * 获取试卷音视频文件列表
     *
     * @param projectId    项目ID
     * @param paperId      试卷ID
     * @param paperVersion 试卷版本号
     * @return
     */
    private List<PaperItemFile> getPaperItemFileData(String projectId, String paperId, String paperVersion) {
        List<PaperItemFile> paperItemFileData = RemoteUtil.getOrThrows(() -> kwClient.getPaperItemFileData(paperId, paperVersion));
        if (CollectionUtil.isEmpty(paperItemFileData)) {
            return paperItemFileData;
        }
        paperItemFileData.forEach(file -> {
            file.setProjectId(projectId);
        });
        return paperItemFileData;
    }

    private void savePaper(Paper paper) {
        try {
            this.save(paper);
        } catch (Exception e) {
            Throwable cause = e.getCause();
            if (cause instanceof SQLIntegrityConstraintViolationException) {
                String sqlState = ((SQLIntegrityConstraintViolationException) cause).getSQLState();
                if (Constants.SQLSTATE_23000.equals(sqlState)) {
                    logger.error("试卷表中已存在主键为：【{},{},{},{},{},{}】的数据，sqlState：{}", paper.getProjectId(), paper.getSubjectId(), paper.getPaperId(), paper.getPaperVersion(), paper.getPackageVersion(),
                            sqlState);
                }
            } else {
                throw e;
            }
        }
    }

    @Override
    public List<Paper> selectParersBySubjectId(String projectId, String subjectId) {
        List<Paper> papers = paperMapper.selectParersBySubjectId(projectId, subjectId);
        return papers;
    }
}
